package nioServer;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class Main {
    private static int port = 8666;
    private static ByteBuffer readBuffer;
    private static Selector selector;

    public static void main(String[] args) throws IOException {
        readBuffer = ByteBuffer.allocate(1024);
        selector = Selector.open();
        ServerSocketChannel socketChannel = ServerSocketChannel.open();
        socketChannel.bind(new InetSocketAddress(port));
        //注册为非阻塞的管道
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true){
            if (selector.select() == 0){
                //等待管道准备的同时 打印
                System.out.println("hehehehda");
                continue;
            }
            Iterator<SelectionKey> iterable = selector.selectedKeys().iterator();
            while (iterable.hasNext()){
                SelectionKey key = iterable.next();
                iterable.remove();
                handleKey(key);
            }
        }
    }
    private static void handleKey(SelectionKey key)
            throws IOException {
        if(key.isAcceptable()) {
            //该key有ACCEPT事件
            //将监听得到的channel强转为ServerSocketChannel
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            //得到接收到的SocketChannel
            SocketChannel socketChannel = server.accept();
            if(socketChannel != null) {
                System.out.println("收到了来自" + ((InetSocketAddress)socketChannel.getRemoteAddress()).getHostString()
                        + "的请求");
                //将socketChannel设置为阻塞模式
                socketChannel.configureBlocking(false);
                //将socketChannel注册到选择器

                socketChannel.register(selector, SelectionKey.OP_READ);
            }
        } else if (key.isReadable()) {
            //该key有Read事件
            SocketChannel socketChannel = (SocketChannel) key.channel();
            String requestHeader = "";
            //拿出通道中的Http头请求
            try {
                requestHeader = receive(socketChannel);
            } catch (Exception e) {
                System.out.println("读取socketChannel出错");
                return;
            }
            //启动线程处理该请求,if条件判断一下，防止心跳包
            if(requestHeader.length() > 0) {
                System.out.println("该请求的头格式为\r\n" + requestHeader);
                System.out.println("启动了子线程..");
//                new Thread(new HttpHandler(requestHeader, key)).start();
            }
        } else if (key.isWritable()) {
            //该key有Write事件
            System.out.println("有流写出!");
            SocketChannel socketChannel = (SocketChannel) key.channel();
            socketChannel.shutdownInput();
            socketChannel.close();
        }
        //从key集合中删除key，这一步很重要，就是因为没写这句，Selector.select()方法一直返回的是0
        //原因分析可能是不从集合中删除，就不会回到I/O就绪事件中
    }

    private static String receive(SocketChannel socketChannel) throws Exception {
        //声明一个1024大小的缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        byte[] bytes = null;
        int size = 0;
        //定义一个字节数组输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //将socketChannel中的数据写入到buffer中，此时的buffer为写模式，size为写了多少个字节
        while ((size = socketChannel.read(buffer)) > 0) {
            //将写模式改为读模式
            //The limit is set to the current position and then the position is set to zero.
            //将limit设置为之前的position，而将position置为0，更多java nio的知识会写成博客的
            buffer.flip();
            bytes = new byte[size];
            //将Buffer写入到字节数组中
            buffer.get(bytes);
            //将字节数组写入到字节缓冲流中
            baos.write(bytes);
            //清空缓冲区
            buffer.clear();
        }
        //将流转回字节数组
        bytes = baos.toByteArray();
        return new String(bytes);
    }

    private static String getAnswer(String question){
        String answer = null;

        switch(question){
            case "who":
                answer = "我是小娜\n";
                break;
            case "what":
                answer = "我是来帮你解闷的\n";
                break;
            case "where":
                answer = "我来自外太空\n";
                break;
            case "hi":
                answer = "hello\n";
                break;
            case "bye":
                answer = "88\n";
                break;
            default:
                answer = "请输入 who， 或者what， 或者where";
        }

        return answer;
    }
}
